#include <iostream>
#include <algorithm>
#include "RandomCL.hpp"
#include "Ordenacao.hpp"
#include <time.h>

using namespace std;

void preencheVetor(unsigned long int *vet, int semente, int n);

int main()
{
    int ntamanhos = 9;
    int ntestes = 6;
    unsigned long int limiarBubble = 90001;
    unsigned long int limiarSelect = 90001;
    unsigned long int limiarInsert = 270001;
    int start, tmili;

    // criar o vetor de tamanhos
    unsigned long int tamanhos[9] = {10000,
                                    30000,
                                    90000,
                                    270000,
                                    810000,
                                    2430000,
                                    7290000,
                                    21870000,
                                    65610000
                                    };

    //loop tamanhos
    for(int i = 0 ; i < ntamanhos; i++){

        unsigned long int *v = new unsigned long int[tamanhos[i]];

        //loop testes
        for(int j = 0; j < ntestes; j++){

            cout << "VETOR: " << tamanhos[i] << ",";
            cout << "TEMPO: " << j << ",";

            //inicio bubbleSort
            //ineficiente -- limiar 2430000
            if(tamanhos[i] < limiarBubble){
                preencheVetor(v, j, tamanhos[i]);

                start = clock();
                ED::Ordenacao<unsigned long int>::bubbleSort(v, tamanhos[i]);
                tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

                cout << tmili << ",";
            }else{
                cout << "n/a" << ",";
            }
            //fim bubbleSort

            //inicio selectSort
            //ineficiente -- limiar 2430000
            if(tamanhos[i] < limiarSelect){
                preencheVetor(v, j, tamanhos[i]);

                start = clock();
                ED::Ordenacao<unsigned long int>::selectSort(v, tamanhos[i]);
                tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

                cout << tmili << ",";
            }else{
                cout << "n/a" << ",";
            }
            //fim selectSort

            //inicio heapSort
            preencheVetor(v, j, tamanhos[i]);

            start = clock();
            ED::Ordenacao<unsigned long int>::heapSort(v, tamanhos[i]);
            tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

            cout << tmili << ",";
            //fim heapSort

            //inicio mergeSort
            preencheVetor(v, j, tamanhos[i]);

            start = clock();
            ED::Ordenacao<unsigned long int>::mergeSort(v, tamanhos[i]);
            tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

            cout << tmili << ",";
            //fim mergeSort

            //inicio insertSort
            if(tamanhos[i] < limiarSelect){
                preencheVetor(v, j, tamanhos[i]);

                start = clock();
                ED::Ordenacao<unsigned long int>::insertSort(v, tamanhos[i]);
                tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

                cout << tmili << ",";
            }else{
                cout << "n/a" << ",";
            }
            //fim insertSort

            //inicio shellSort
            preencheVetor(v, j, tamanhos[i]);

            start = clock();
            ED::Ordenacao<unsigned long int>::shellSort(v, tamanhos[i]);
            tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

            cout << tmili << ",";
            //fim shellSort

            //inicio shellSort_knuth
            preencheVetor(v, j, tamanhos[i]);

            start = clock();
            ED::Ordenacao<unsigned long int>::shellSort_knuth(v, tamanhos[i]);
            tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

            cout << tmili << ",";
            //fim shellSort_knuth

            //inicio shellSort_pardons
            preencheVetor(v, j, tamanhos[i]);

            start = clock();
            ED::Ordenacao<unsigned long int>::shellSort_pardons(v, tamanhos[i]);
            tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

            cout << tmili << ",";
            //fim shellSort_pardons

            //inicio quickSort
            preencheVetor(v, j, tamanhos[i]);

            start = clock();
            ED::Ordenacao<unsigned long int>::quickSort(v, tamanhos[i]);
            tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

            cout << tmili << ",";
            //fim quickSort

            //inicio Sort do c++
            preencheVetor(v, j, tamanhos[i]);

            start = clock();
            ED::Ordenacao<unsigned long int>::sortCPlusPlus(v, tamanhos[i]);
            tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

            cout << tmili << ",";
            //fim Sort do c++


             //inicio QSort do c Standard
            preencheVetor(v, j, tamanhos[i]);

            start = clock();
            ED::Ordenacao<unsigned long int>::qsortCStandard(v, tamanhos[i]);
            tmili = (int)((clock()-start)*1000/CLOCKS_PER_SEC);

            cout << tmili;
            //fim QSort do c Standard


            cout << endl;
        }

    }



    return 0;
}

void preencheVetor(unsigned long int *vet, int semente, int n){
    int i = 0;
    // instancia do gerador a ser usado com semente
    RandomCL<unsigned long int> gerador(semente);
    while(i < n)
    {
        //gera valor
        vet[i] = gerador.nextr();
        i++;
    }
    //limpa gerador
    gerador.reset();
}
